home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Mac-Source 1994 July
/
Mac-Source_July_1994.iso
/
C and C++
/
Compilers⁄Interps
/
kevoSource
/
context.c
< prev
next >
Wrap
Text File
|
1993-05-14
|
26KB
|
1,052 lines
/* Kevo -- a prototype-based object-oriented language */
/* (c) Antero Taivalsaari 1991-1993 */
/* Some parts (c) Antero Taivalsaari 1986-1988 */
/* context.c: Name space (context) management internals */
#include "global.h"
#include "portGlobal.h"
/*--------------------------------------------------------------------------*/
/* Context management operations */
PAIR* LatestPair; /* Pointer to the latest name in the dictionary */
/* Needed only for setting flags after 'addPair' */
/* hash(): hash function */
/* inlined for speed (see the header file 'context.h')
int hash(identifier)
char* identifier;
{
return((int)*identifier % CONTEXTSIZE);
}
*/
/* lowCreateContext(): low-level context creation */
CONTEXT* lowCreateContext()
{
return((CONTEXT*)mycalloc(1, sizeof(CONTEXT)));
}
/* xCreateContext(): another low-level context creation */
/* which is needed only in root context initialization */
/* Since 'dummyContext' and (=context) have not been defined */
/* when initializing root contexts, we cannot initialize */
/* the clone families of these contexts (using createList) */
CONTEXT* xCreateContext()
{
CONTEXT* newContext = lowCreateContext();
/* Attach the context to the end of the global context list */
if (lastContext) {
lastContext->nextContext = newContext;
lastContext = newContext;
}
return(newContext);
}
/* createContext(): create and initialize a new context (high-level) */
CONTEXT* createContext()
{
CONTEXT* newContext = xCreateContext();
/* Initialize the family lists */
newContext->cloneFamily = createList();
newContext->parentFamilies = createList();
newContext->childFamilies = createList();
return(newContext);
}
/* copyContext(): duplicate an existing context with all its names */
/* this operation is needed internally when new clone families are */
/* being derived. Note that family lists are not copied (shallow copy) */
CONTEXT* copyContext(oldC)
CONTEXT* oldC;
{
CONTEXT* newC;
PAIR* oldPair = oldC->firstPair;
PAIR* newPair;
newC = createContext();
while (oldPair) {
newPair = addPair(newC, oldPair->nfa, oldPair->ofa);
newPair->ffa = oldPair->ffa; /* Duplicate flag field too */
oldPair = oldPair->sfa;
}
return(newC);
}
/* This operation is needed only internally in the next operation */
/* to find the previous context in the context list */
CONTEXT* findPrevContext(context)
CONTEXT* context;
{
/* The first context in the context list is always 'rootContext' */
CONTEXT* thisContext = rootContext;
while (thisContext) {
if (thisContext->nextContext == context) return(thisContext);
thisContext = thisContext->nextContext;
}
fprintf(confile, "== Integrity error detected: context link damaged (no prev ctxt found) ==\n");
reportIntegrityError();
ownLongJmp();
}
/* deleteContext(): delete an existing context with all its names. */
/* Note that family lists are not deleted (must be done separately) */
/* Remember that contexts are linked in a singly-linked list so as */
/* to allow type name lookup, so we must remove the context from */
/* that list too */
void deleteContext(context)
CONTEXT* context;
{
CONTEXT* prevCtxt = findPrevContext(context);
CONTEXT* nextCtxt = context->nextContext;
PAIR* thisPair = context->firstPair;
/* Remove the context from the context list */
if (prevCtxt) {
prevCtxt->nextContext = nextCtxt;
if (lastContext == context) lastContext = prevCtxt;
}
else {
fprintf(confile, "== Integrity error detected: attempt to remove 'rootContext' ==\n");
reportIntegrityError();
ownLongJmp();
}
/* Deallocate the pairs */
while (thisPair) {
PAIR* tempPair = thisPair->sfa;
free(thisPair);
thisPair = tempPair;
}
/* Deallocate the context itself */
free(context);
}
/* comparePairs(): compare if two pairs are equivalent.
The comparison is based on the equivalence of names,
encapsulation flags, and operations.
The equality of operations is based simply on the identity
of the operations (physically same code) rather than behavioral
comparison. More clever schemes should be examined later.
The operation returns TRUE if the pairs are equal.
*/
int comparePairs(pair1, pair2)
PAIR* pair1;
PAIR* pair2;
{
if (!pair1) return(FALSE);
if (!pair2) return(FALSE);
if (pair1->ofa != pair2->ofa) return(FALSE);
if (strcmp(pair1->nfa, pair2->nfa) != 0) return(FALSE);
if (pair1->ffa != pair2->ffa) return(FALSE);
return(TRUE);
}
/* compareContexts(): compare if two contexts are equivalent.
The operation returns TRUE if the contexts are equal.
*/
int compareContexts(context1, context2)
CONTEXT* context1;
CONTEXT* context2;
{
PAIR* thisPair1 = context1->firstPair;
PAIR* thisPair2 = context2->firstPair;
while (thisPair1) {
/* Any incompatible pair will cause the comparison to fail */
if (!comparePairs(thisPair1, thisPair2)) return(FALSE);
thisPair1 = thisPair1->sfa;
thisPair2 = thisPair2->sfa;
}
if (thisPair2) return(FALSE);
else return(TRUE);
}
/* compareContextResemblance(): compare if two context
have at least something in common (at least one of
the properties in them is exactly the same)
*/
int compareContextResemblance(context1, context2)
CONTEXT* context1;
CONTEXT* context2;
{
PAIR* thisPair1 = context1->firstPair;
PAIR* thisPair2;
while (thisPair1) {
thisPair2 = context2->firstPair;
while (thisPair2) {
/* Any compatible pair will cause the comparison to succeed */
if (comparePairs(thisPair1, thisPair2)) return(TRUE);
thisPair2 = thisPair2->sfa;
}
thisPair1 = thisPair1->sfa;
}
return(FALSE);
}
/* isContextObject(): check if a given object is */
/* a proper OOP object with its own context */
/* This operation is fairly slow, and is used mainly in the browser */
int isContextObject(object)
OBJECT* object;
{
if (maskedFetch((int*)object) && maskedFetch((int*)object->mfa))
return(object->mfa->efa == (int*)oContext ? TRUE : FALSE);
else return(FALSE);
}
/* getContext(): given an OOP object, return the corresponding context */
/* Inlined for speed (see the header file 'global.h'
CONTEXT* getContext(object)
OBJECT* object;
{
return((CONTEXT*)object->mfa->pfa);
}
*/
/* initRootContexts(): initialize the root context. */
/* This operation is needed in 'main.c' */
void initRootContexts()
{
/* Create an "empty" dummy context. This is useful for some objects */
/* so that we can view them as objects from the browser */
dummyContext = lowCreateContext();
/* Create a root context for system primitives */
/* This is known as 'SystemRoot' in the high-level Kevo */
rootContext = lastContext = xCreateContext();
/* Create a root context for user-given definitions */
/* This is known as 'Root' in the high-level Kevo */
userContext = xCreateContext();
}
/* initRootFamilies(): initialize the clone family lists */
/* of basic contexts. These could not be initialized property */
/* earlier, because '(=context)' and dummyContext were not */
/* declared when calling 'createList()' */
void initRootFamilies()
{
dummyContext->cloneFamily = createList();
dummyContext->parentFamilies = createList();
dummyContext->childFamilies = createList();
rootContext->cloneFamily = createList();
rootContext->parentFamilies = createList();
rootContext->childFamilies = createList();
userContext->cloneFamily = createList();
userContext->parentFamilies = createList();
userContext->childFamilies = createList();
}
/*--------------------------------------------------------------------------*/
/* Pair (name) specific context operations */
/* addPair(): add a new pair to an existing context */
PAIR* addPair(context, identifier, referent)
CONTEXT* context;
char* identifier;
OBJECT* referent;
{
int thread = hash(identifier);
/* Allocate a new pair */
PAIR* newPair = (PAIR*)mymalloc(sizeof(PAIR));
/* Initialize fields */
newPair->nfa = identifier; /* Note that the string is not copied */
newPair->ofa = referent; /* The object */
newPair->cfa = context; /* Pair contains a backpointer to the context */
newPair->ffa = 0; /* Flags are all down at first */
/* Add the new pair to the end of the correct thread in context */
newPair->lfa = context->lastPair[thread];
context->lastPair[thread] = newPair;
/* Set also the reverse link */
if (context->latestPair) context->latestPair->sfa = newPair;
else context->firstPair = newPair;
context->latestPair = newPair;
newPair->sfa = NIL;
/* Set the global variable to point to the latest pair */
LatestPair = newPair;
return(newPair);
}
/* findSurroundings: find the surrounding four pairs for the given pair.
This operation is used only internally in some dictionary manipulation
operations to allow easy link manipulation.
*/
void findSurroundings(thePair, theThread, prevPair, succPair, prevInThread, succInThread)
PAIR* thePair;
int theThread;
PAIR** prevPair; /* Previous pair in the context before 'thePair' */
PAIR** succPair; /* Next pair in the context after 'thePair' */
PAIR** prevInThread; /* Previous pair in 'theThread' before 'thePair' */
PAIR** succInThread; /* Next pair in 'theThread' after 'thePair' */
{
CONTEXT* context = thePair->cfa;
PAIR* thisPair = context->firstPair;
/* Initialize the return values */
*prevPair = NIL;
*succPair = thePair->sfa;
*prevInThread = NIL;
*succInThread = NIL;
while (thisPair) {
if (thisPair == thePair) goto forward;
if (hash(thisPair->nfa) == theThread) *prevInThread = thisPair;
*prevPair = thisPair;
thisPair = thisPair->sfa;
}
/* 'thePair' was not found in the context -> serious error */
fprintf(confile, "== Integrity error detected: pair not found in 'findSurroundings' ==\n");
reportIntegrityError();
ownLongJmp();
forward:
/* Find the next pair in the requested thread */
while ((thisPair = thisPair->sfa) != NIL) {
if (hash(thisPair->nfa) == theThread) {
*succInThread = thisPair;
break;
}
}
}
/* unlinkPair(): remove a pair from a context */
/*
Remember that we must unlink the pair from both directions.
This is a bit problematic, since to the other direction
dictionary is hashed (multi-linked), and to the other there is
only a singly linked list.
*/
void unlinkPair(pair)
PAIR* pair;
{
CONTEXT* context = pair->cfa;
int thread = hash(pair->nfa);
PAIR* prevPair;
PAIR* succPair;
PAIR* prevInThread;
PAIR* succInThread;
findSurroundings(pair, thread, &prevPair, &succPair, &prevInThread, &succInThread);
/* Remove the pair from the successor link */
if (prevPair)
prevPair->sfa = pair->sfa;
else context->firstPair = pair->sfa;
if (succPair == NIL) context->latestPair = prevPair;
/* Remove the pair from the predecessor link */
if (succInThread)
succInThread->lfa = pair->lfa;
else context->lastPair[thread] = pair->lfa;
}
/* renamePair(): rename a pair in a context */
/*
This operation is also a bit problematic to implement owing
to the hashed (multi-linked) structure of the dictionary.
*/
void renamePair(oldPair, newName)
PAIR* oldPair;
char* newName;
{
CONTEXT* context = oldPair->cfa;
int oldThread = hash(oldPair->nfa);
int newThread = hash(newName);
PAIR* newPair;
PAIR* thisPair;
PAIR* succInThread;
/*
If the new name hashes to the same link than the previous one,
things are simple, and we can directly change the name field.
*/
if (oldThread == newThread) {
oldPair->nfa = newName;
return;
}
/*
Otherwise, things get a bit more complicated.
Fortunately, the pairs are linked together also to the other
direction. The successor link is only singly linked (unhashed),
so we know the exact definition order of pairs.
*/
/* Allocate a new pair */
newPair = (PAIR*)mymalloc(sizeof(PAIR));
/* Initialize/copy the fields */
newPair->nfa = newName;
newPair->ofa = oldPair->ofa;
newPair->cfa = oldPair->cfa;
newPair->ffa = oldPair->ffa;
/* New pair will be added right after the old one in the successor link */
/* Locate the next pair in the new thread after 'oldPair' */
thisPair = oldPair;
succInThread = NIL;
while (thisPair) {
if (hash(thisPair->nfa) == newThread) {
succInThread = thisPair;
break;
}
thisPair = thisPair->sfa;
}
/* Insert the new pair to the insertion point */
newPair->sfa = oldPair->sfa;
oldPair->sfa = newPair;
if (succInThread) {
newPair->lfa = succInThread->lfa;
succInThread->lfa = newPair;
}
else {
newPair->lfa = context->lastPair[newThread];
context->lastPair[newThread] = newPair;
}
if (context->latestPair == oldPair)
context->latestPair = newPair;
/* Finally, remove the old pair from the context */
unlinkPair(oldPair);
free(oldPair);
}
/* hide(): make the latest pair "hidden" */
void hide()
{
LatestPair->ffa |= HiddenFlag;
}
/* copyPair(): make a copy of a pair */
/* This operation is needed for the user interface (CUT, COPY, PASTE) */
PAIR* copyPair(oldPair)
PAIR* oldPair;
{
PAIR* newPair = (PAIR*)mymalloc(sizeof(PAIR));
/* Copy fields */
*newPair = *oldPair;
return(newPair);
}
/* addBeforePair(): link the given pair in front of the requested pair */
/*
This operation allows new properties to be added to arbitrary
points within objects, and it is needed for the user interface
(CUT, COPY, PASTE).
Different cases:
1) if the context is empty before addition (should not happen)
2) if added before the first pair in the context
3) if added before the first pair in a thread
4) other
*/
PAIR* addBeforePair(beforePair, newPair)
PAIR* beforePair; /* The pair before which the new pair is added */
PAIR* newPair; /* The pair to be added */
{
CONTEXT* context = beforePair->cfa;
int beforeThread = hash(beforePair->nfa);
int newThread = hash(newPair->nfa);
PAIR* prevPair;
PAIR* succPair;
PAIR* prevInThread;
PAIR* succInThread;
findSurroundings(beforePair, newThread, &prevPair, &succPair, &prevInThread, &succInThread);
/* Add the pair to the successor link */
newPair->sfa = beforePair;
if (prevPair)
prevPair->sfa = newPair;
else context->firstPair = newPair;
/* Add the pair to the predecessor link */
newPair->lfa = prevInThread;
/*
If we are adding to the same thread, then the successor
is the 'beforePair' rather than its successor.
*/
if (beforeThread == newThread) succInThread = beforePair;
if (succInThread)
succInThread->lfa = newPair;
else context->lastPair[newThread] = newPair;
/* Finally, change the new pair's context field to 'context' */
newPair->cfa = context;
return(newPair);
}
/*--------------------------------------------------------------------------*/
/* Finding operations (used in searching names and objects from contexts) */
/* findPairInThis(): find a pair from a specific context given a string */
PAIR* findPairInThis(context, identifier)
CONTEXT* context;
char* identifier;
{
int thread = hash(identifier);
register PAIR* tempPair = context->lastPair[thread];
while (tempPair) {
if (!(tempPair->ffa & SmudgeFlag) &&
strcmp(tempPair->nfa, identifier) == 0)
return(tempPair);
tempPair = tempPair->lfa;
}
return(NIL);
}
/* findPairBackward(): find a pair using a certain search order. */
/* First the current context (self) will be searched, then 'Root' */
/* (user-level root) and finally 'SystemRoot' (system primitives). */
PAIR* findPairBackward(identifier)
char* identifier;
{
register PAIR* thisPair;
if (thisPair = findPairInThis(getContext((OBJECT*)topContext), identifier))
return(thisPair);
if (thisPair = findPairInThis(userContext, identifier))
return(thisPair);
if (thisPair = findPairInThis(rootContext, identifier))
return(thisPair);
return(NIL);
}
/* findNameInThis(): find a matching pair for a given object in a specific context */
PAIR* findNameInThis(context, object)
CONTEXT* context;
OBJECT* object;
{
int thread;
for (thread = 0; thread < CONTEXTSIZE; thread++) {
PAIR* tempPair = context->lastPair[thread];
while (tempPair) {
if (!(tempPair->ffa & SmudgeFlag) && tempPair->ofa == object)
return(tempPair);
tempPair = tempPair->lfa;
}
}
return(NIL);
}
/* findNameBackward(): find a matching pair using a backward search order */
/* see 'findPairBackward' above */
PAIR* findNameBackward(object)
OBJECT* object;
{
PAIR* thisPair;
if (!maskedFetch((int*)object)) return(NIL);
if (thisPair = findNameInThis(getContext((OBJECT*)topContext), object))
return(thisPair);
if (thisPair = findNameInThis(userContext, object))
return(thisPair);
if (thisPair = findNameInThis(rootContext, object))
return(thisPair);
return(NIL);
}
/* findNameForward(): find a matching pair by searching all the contexts */
/* in the first-defined-first order */
PAIR* findNameForward(object)
OBJECT* object;
{
CONTEXT* thisContext = rootContext;
PAIR* thisPair;
if (!maskedFetch((int*)object)) return(NIL);
while (thisContext) {
if (thisPair = findNameInThis(thisContext, object)) return(thisPair);
thisContext = thisContext->nextContext;
}
return(NIL);
}
/* findTypeInThis(): find a matching object for a given context object */
/* This object is the "type" of that context */
/*
This operation is needed for object-oriented programming to print the
types of objects automatically. Compared to other finding operations,
the search order in this operation is backwards (from the earlier defined
things towards later defined ones).
Due to the very indirect nature of objects in our system, this operation
is admittedly rather complicated. Furthermore, possible bus errors caused
by high memory references must be avoided, causing extra complexity.
*/
PAIR* findTypeInThis(context, ctxtObject)
CONTEXT* context;
OBJECT* ctxtObject;
{
CONTEXT* desiredCtxt;
PAIR* tempPair;
desiredCtxt = getContext(ctxtObject);
tempPair = context->firstPair;
while (tempPair) {
if (!(tempPair->ffa & SmudgeFlag)) {
OBJECT* object = tempPair->ofa;
/* We search mainly for REF objects */
if (object && object->sfa == DATAOFFSET &&
(object = (OBJECT*)object->mfa->pfa)) {
if (maskedFetch((int*)object) &&
object->sfa > 0 &&
object->mfa->efa == (int*)oContext &&
object->mfa->pfa == (int*)desiredCtxt) return(tempPair);
}
}
tempPair = tempPair->sfa; /* get next pair */
}
return(NIL);
}
/* findTypeForward(): this is the generalization of 'findTypeInThis()' */
/* Search through all the contexts using their definition order list */
PAIR* findTypeForward(ctxtObject)
OBJECT* ctxtObject;
{
CONTEXT* thisContext = userContext;
PAIR* thisPair;
if (!isContextObject(ctxtObject)) return(NIL);
while(thisContext) {
if (thisPair = findTypeInThis(thisContext, ctxtObject)) return(thisPair);
thisContext = thisContext->nextContext;
}
return(NIL);
}
/* findPrimName(): find the name part of a primitive function. */
/* It is assumed that C primitives reside only in the system root context, */
/* so we search only that context. */
PAIR* findPrimName(prim)
int* prim;
{
int thread;
for (thread = 0; thread < CONTEXTSIZE; thread++) {
PAIR* tempPair = rootContext->lastPair[thread];
while (tempPair) {
if (tempPair->ofa && tempPair->ofa->mfa == (STORE*)prim) return(tempPair);
tempPair = tempPair->lfa;
}
}
return(NIL);
}
/* ------------------------------------------------------------------------ */
/* Context operations for object-oriented programming */
/* nonSelfLookUp(): find a matching pair in the context starting */
/* from a given pair, but accept only the non-hidden properties. */
PAIR* nonSelfLookUp(thisPair, identifier)
PAIR* thisPair;
char* identifier;
{
while (thisPair) {
if (strcmp(thisPair->nfa, identifier) == 0 && !(thisPair->ffa & HiddenFlag))
return(thisPair);
thisPair = thisPair->lfa;
}
return(NIL);
}
/* selfLookUp(): find a matching pair in the context starting */
/* from a given pair, accepting also the hidden properties. */
PAIR* selfLookUp(thisPair, identifier)
PAIR* thisPair;
char* identifier;
{
while (thisPair) {
if (strcmp(thisPair->nfa, identifier) == 0) return(thisPair);
thisPair = thisPair->lfa;
}
return(NIL);
}
/* messageLookUp(): basic lookup routine for object-oriented programming. */
/* find a matching pair in the given context object, but search the non-hidden */
/* (not encapsulated) properties only if the message comes from outside 'self' */
PAIR* messageLookUp(object, identifier)
OBJECT* object;
char* identifier;
{
CONTEXT* context = getContext(object);
int thread = hash(identifier);
PAIR* thisPair = context->lastPair[thread];
if (object == (OBJECT*)topContext) {
/* 'selfLookUp() "inlined" for speed */
while (thisPair) {
if (strcmp(thisPair->nfa, identifier) == 0) return(thisPair);
thisPair = thisPair->lfa;
}
}
else {
/* nonSelfLookUp() "inlined" for speed */
while (thisPair) {
if (strcmp(thisPair->nfa, identifier) == 0 && !(thisPair->ffa & HiddenFlag))
return(thisPair);
thisPair = thisPair->lfa;
}
return(NIL);
}
}
/* respondsTo(): test if a certain object responds to a certain message */
/* This operation does not refer to context stack, so it can invoked also */
/* by the user interface */
PAIR* respondsTo(object, identifier)
OBJECT* object;
char* identifier;
{
CONTEXT* context = getContext(object);
int thread = hash(identifier);
PAIR* startPair = context->lastPair[thread];
return nonSelfLookUp(startPair, identifier);
}
/* getREFslot(): gets the storage address of a REF (SHAREDVAR) or CONST slot */
OBJECT** getREFslot(thisPair)
PAIR* thisPair;
{
STORE* store;
if (thisPair->ofa && (store = thisPair->ofa->mfa))
return((OBJECT**)&store->pfa);
else return(NIL);
}
/* getVARoffset(): gets the offset of a VAR slot */
/* Remember: data slots are offseted with DATAOFFSET */
/* (i.e., the offset to the first data slot is 2, second = 3, ...) */
int getVARoffset(thisPair)
PAIR* thisPair;
{
OBJECT** offsetAddr = getREFslot(thisPair);
if (offsetAddr)
return((int)*offsetAddr);
else return(0);
}
/* getVARslot(): gets the storage address of a VAR slot */
OBJECT** getVARslot(ctxtObject, thisPair)
OBJECT* ctxtObject;
PAIR* thisPair;
{
int offset = getVARoffset(thisPair);
return((OBJECT**)((int**)ctxtObject->mfa + offset));
}
/* countAllPairs(): count all the pairs in the given context */
int countAllPairs(context)
CONTEXT* context;
{
PAIR* thisPair = context->firstPair;
int count = 0;
while (thisPair) {
count++;
thisPair = thisPair->sfa;
}
return(count);
}
/* countDataPairs(): count the data pairs in the given context */
/* (REF, VAR, SHAREDVAR, CONST) */
int countDataPairs(context)
CONTEXT* context;
{
PAIR* thisPair = context->firstPair;
int count = 0;
while (thisPair) {
if (thisPair->ofa) switch(recognizeObject(thisPair->ofa)) {
case REF:
case VAR:
case CONST:
count++;
break;
}
thisPair = thisPair->sfa;
}
return(count);
}
/* countOperPairs(): count the method pairs in the given context */
int countOperPairs(context)
CONTEXT* context;
{
PAIR* thisPair = context->firstPair;
int count = 0;
while (thisPair) {
if (thisPair->ofa) switch(recognizeObject(thisPair->ofa)) {
case PRIMITIVE:
case METHOD:
count++;
break;
}
thisPair = thisPair->sfa;
}
return(count);
}
/* findAllAsIndexed(): find the n'th pair in the given context */
PAIR* findAllAsIndexed(context, index)
CONTEXT* context;
int index;
{
PAIR* tempPair = context->firstPair;
while (--index && tempPair) tempPair = tempPair->sfa;
return(tempPair);
}
/* findDataAsIndexed(): find the n'th data pair in the given context */
PAIR* findDataAsIndexed(context, index)
CONTEXT* context;
int index;
{
PAIR* tempPair = context->firstPair;
while (tempPair) {
if (tempPair->ofa) switch(recognizeObject(tempPair->ofa)) {
case REF:
case VAR:
case CONST:
if (--index == 0) return(tempPair);
break;
}
tempPair = tempPair->sfa;
}
return(NIL);
}
/* findOperAsIndexed(): find the n'th method pair in the given context */
PAIR* findOperAsIndexed(context, index)
CONTEXT* context;
int index;
{
PAIR* tempPair = context->firstPair;
while (tempPair) {
if (tempPair->ofa) switch(recognizeObject(tempPair->ofa)) {
case PRIMITIVE:
case METHOD:
if (--index == 0) return(tempPair);
break;
}
tempPair = tempPair->sfa;
}
return(NIL);
}
/* Check the integrity of the given context by performing several checks */
void checkIntegrity(context)
CONTEXT* context;
{
int fwdCount = countAllPairs(context);
int bwdCount = 0;
int thread;
int error = FALSE;
for (thread = 0; thread < CONTEXTSIZE; thread++) {
PAIR* thisPair = context->lastPair[thread];
PAIR* tempPair;
while (thisPair) {
bwdCount++;
if (hash(thisPair->nfa) != thread) {
fprintf(confile, "== Integrity error detected: name in wrong thread ==\n");
error = TRUE;
}
if (thisPair->cfa != context) {
fprintf(confile, "== Integrity error detected: name in wrong context ==\n");
error = TRUE;
}
tempPair = context->firstPair;
while (tempPair) {
if (tempPair == thisPair) goto forw1;
tempPair = tempPair->sfa;
}
fprintf(confile, "== Integrity error detected: name not found in successor link ==\n");
error = TRUE;
forw1:
thisPair = thisPair->lfa;
}
}
if (fwdCount != bwdCount) {
fprintf(confile, "== Integrity error detected: link counts do no match ==\n");
error = TRUE;
}
if (fwdCount) {
if (context->latestPair == NIL) {
fprintf(confile, "== Integrity error detected: latest pair is NIL although context isn't empty ==\n");
error = TRUE;
}
}
if (bwdCount) {
if (context->firstPair == NIL) {
fprintf(confile, "== Integrity error detected: first pair is NIL although context isn't empty == \n");
error = TRUE;
}
}
if (context->latestPair != NIL) {
for (thread = 0; thread < CONTEXTSIZE; thread++) {
if (context->lastPair[thread] == context->latestPair) goto forw2;
}
fprintf(confile, "== Integrity error detected: latest pair not found among last pairs ==\n");
error = TRUE;
}
if (!checkFamilyIntegrity(context)) error = TRUE;
forw2:
if (error) reportIntegrityError();
}